#include "bcmc_cnckernel.h"
#include <bcm/bcm.h>
#include <iostream>

class CNCMode : public cnc::base::CooperativeMode
{
protected:
	static const char *modeName_[];
	cnc::base::BCMI_KernelSetup *coordinator_;
	const cnc::base::OperationModeID thisMode_;
	int menu()
	{
		int option;
		for (int i = 0; i < 8; i++)
			std::cout << "\t" << i + 1 << ". " << modeName_[i] << std::endl;
		std::cout << "\t9. Exit" << std::endl;
		std::cin >> option;
		return option;
	}
public:
	CNCMode(cnc::base::OperationModeID thisMode, cnc::base::BCMI_KernelSetup *coordinator)
		: thisMode_(thisMode), coordinator_(coordinator)
	{
	}
	virtual bool start()
	{
		std::cout << "Start " << modeName_[thisMode_] << std::endl;
		return true;
	}
	virtual bool execute()
	{
		std::cout << "---" << modeName_[thisMode_] << "---" << std::endl;
		cnc::base::OperationModeID nextMode = static_cast<cnc::base::OperationModeID>(menu() - 1);
		if (nextMode != 8) {
			std::cout << modeName_[nextMode] << " selected." << std::endl;
			if (nextMode != thisMode_) {
				coordinator_->selectMode(nextMode);
				return false;
			}
			return true;
		}
		return false;
	}
	virtual bool stop()
	{
		std::cout << "Stop " << modeName_[thisMode_] << std::endl;
		return true;
	}
};

const char *CNCMode::modeName_[] = {
	"Setup Mode",
	"MDI Mode",
	"Jog Mode",
	"Rapid Mode",
	"Handwheel Mode",
	"Memory Mode",
	"File Manager Mode",
	"Edit Mode"
};

class BackgroundTask : public cnc::base::CooperativeTask
{
public:
	virtual bool start()
	{
		std::cout << "Start background task." << std::endl;
		return true;
	}
	virtual bool execute()
	{
		std::cout << "Execute background task." << std::endl;
		return true;
	}
	virtual bool stop()
	{
		std::cout << "Stop background task." << std::endl;
		return true;
	}
};

int main()
{
	bcm::ComponentManager &compMgr = bcm::ComponentManager::instance();
	switch (compMgr.loadComponent(TEXT("cnckernel.dll"))) {
	case bcm::LC_NODLL:
		std::cout << "Could not load cnckernel.dll." << std::endl;
		return 1;
	case bcm::LC_NOCOMPONENT:
		std::cout << "No component contained in cnckernel.dll." << std::endl;
		return 1;
	case bcm::LC_ALREADYUSED:
		std::cout << "Component \"cnckrnl\" already registered." << std::endl;
		return 1;
	case bcm::LC_OK:
		std::cout << "Component \"cnckrnl\" properly loaded from cnckernel.dll." << std::endl;
		break;
	}
	bcm::Component *component;
	switch (compMgr.getComponent("cnckrnl", &component)) {
	case bcm::GC_UNREGISTERED:
		std::cout << "Component \"cnckrnl\" was never registered." << std::endl;
		return 1;
	case bcm::GC_NOCOMPONENT:
		std::cout << "Component \"cnckrnl\" not available in DLL." << std::endl;
		return 1;
	case bcm::GC_INCOMPLETE:
		std::cout << "Component \"cnckrnl\" incomplete." << std::endl;
		return 1;
	case bcm::GC_OK:
		std::cout << "Component \"cnckrnl\" properly loaded." << std::endl;
		break;
	}
	bcm::Interface *iface;
	iface = component->getInterface("krnlsetup");
	cnc::base::BCMI_KernelSetup *setup = dynamic_cast<cnc::base::BCMI_KernelSetup *>(iface);
	CNCMode setupMode(cnc::base::OPMODE_SETUP, setup);
	CNCMode mdiMode(cnc::base::OPMODE_MDI, setup);
	CNCMode jogMode(cnc::base::OPMODE_JOG, setup);
	CNCMode rapidMode(cnc::base::OPMODE_RAPID, setup);
	CNCMode handwheelMode(cnc::base::OPMODE_HANDWHEEL, setup);
	CNCMode memoryMode(cnc::base::OPMODE_MEMORY, setup);
	CNCMode tapeMode(cnc::base::OPMODE_TAPE, setup);
	CNCMode editMode(cnc::base::OPMODE_EDIT, setup);
	BackgroundTask bgTask;
	setup->addTask(&bgTask);
	setup->addMode(cnc::base::OPMODE_SETUP, &setupMode);
	setup->addMode(cnc::base::OPMODE_MDI, &mdiMode);
	setup->addMode(cnc::base::OPMODE_JOG, &jogMode);
	setup->addMode(cnc::base::OPMODE_RAPID, &rapidMode);
	setup->addMode(cnc::base::OPMODE_HANDWHEEL, &handwheelMode);
	setup->addMode(cnc::base::OPMODE_MEMORY, &memoryMode);
	setup->addMode(cnc::base::OPMODE_TAPE, &tapeMode);
	setup->addMode(cnc::base::OPMODE_EDIT, &editMode);
	setup->selectMode(cnc::base::OPMODE_SETUP);
	iface = component->getInterface("taskctl");
	cnc::base::BCMI_TaskControl *control = dynamic_cast<cnc::base::BCMI_TaskControl *>(iface);
	control->start();
	control->execute();
	control->stop();
	return 0;
}

